package com.liliudong.template.impl;

import com.liliudong.template.common.constant.DataScopeConst;
import com.liliudong.template.common.entity.sys.SysRole;
import com.liliudong.template.common.security.util.SecurityUtil;
import com.mybatisflex.core.constant.SqlOperator;
import com.mybatisflex.core.dialect.impl.CommonsDialectImpl;
import com.mybatisflex.core.query.*;

import java.util.List;
import java.util.Objects;
import java.util.Set;

import static com.liliudong.template.common.entity.sys.table.SysDeptTableDef.SYS_DEPT;
import static com.liliudong.template.common.entity.sys.table.SysRoleDeptTableDef.SYS_ROLE_DEPT;
import static com.liliudong.template.common.entity.sys.table.SysUserRoleTableDef.SYS_USER_ROLE;

public class DataPermissionDialectImpl extends CommonsDialectImpl {

    private static final String CREATED_FROM = "created_from";
    private static final String CREATED_BY = "created_by";

    @Override
    public String forSelectByQuery(QueryWrapper queryWrapper) {
        List<QueryTable> tables = CPI.getQueryTables(queryWrapper);
        boolean ignoreDataPermission = tables.stream()
                .map(QueryTable::getAlias)
                .anyMatch(DataScopeConst.IGNORE_TABLE_ALIAS::equals);
        if (ignoreDataPermission) {
            return super.buildSelectSql(queryWrapper);
        }
        // 获取主表 - 默认第一表就是主表
        QueryTable mainTable = tables.get(0);
        // 执行数据权限
        long loginUserId = SecurityUtil.getLoginUserId();
        Set<SysRole.DataScope> dataScopes = SecurityUtil.getDataScopes();
        String deptNo = SecurityUtil.getDeptNo();

        // 固定范围按照范围大优先
        SysRole.DataScope dataScopeWithNonCustomization = getDataScopeWithNonCustomization(dataScopes);
        if (Objects.equals(SysRole.DataScope.ALL, dataScopeWithNonCustomization)) {
            // 查询全部数据 不拼接SQL
            return super.buildSelectSql(queryWrapper);
        }

        if (Objects.equals(SysRole.DataScope.SELF, dataScopeWithNonCustomization)) {
            // 只查询自己的数据 拼接SQL create_by = userId
            queryWrapper.and(
                    QueryCondition.create(
                            new QueryColumn(mainTable.getSchema(), mainTable.getName(), CREATED_BY, mainTable.getAlias()),
                            SqlOperator.EQUALS,
                            loginUserId
                    )
            );
        } else if (Objects.equals(SysRole.DataScope.DEPARTMENT, dataScopeWithNonCustomization)) {
            // 查询本部门的数据 拼接SQL created_from = dept_no
            queryWrapper.and(
                    QueryCondition.create(
                            new QueryColumn(mainTable.getSchema(), mainTable.getName(), CREATED_FROM, mainTable.getAlias()),
                            SqlOperator.EQUALS,
                            deptNo
                    )
            );
        } else if (Objects.equals(SysRole.DataScope.DEPARTMENT_AND_SUBORDINATE, dataScopeWithNonCustomization)) {
            // 查询本部门及以下的数据 拼接SQL created_from like 'dept_no%'
            queryWrapper.and(
                    QueryCondition.create(
                            new QueryColumn(mainTable.getSchema(), mainTable.getName(), CREATED_FROM, mainTable.getAlias()),
                            SqlOperator.LIKE_LEFT,
                            deptNo
                    )
            );
        }
        // 自定义数据范围
        if (dataScopes.contains(SysRole.DataScope.CUSTOMIZE)) {
            // 自定义数据范围 拼接SQL
            queryWrapper.in(
                    CREATED_FROM,
                    QueryChain.create(SYS_DEPT)
                            .select(SYS_DEPT.DEPT_NO)
                            .innerJoin(SYS_ROLE_DEPT)
                            .on(SYS_DEPT.ID.eq(SYS_ROLE_DEPT.DEPT_ID))
                            .innerJoin(SYS_USER_ROLE)
                            .on(SYS_ROLE_DEPT.ROLE_ID.eq(SYS_USER_ROLE.ROLE_ID))
                            .where(
                                    SYS_USER_ROLE.USER_ID.eq(loginUserId)
                                            .and(SYS_DEPT.DELETED.eq(0))
                            )
            );
        }
        return super.buildSelectSql(queryWrapper);
    }

    /**
     * 获取非自定义数据范围
     *
     * @param dataScopes 数据作用域
     * @return int
     */
    private static SysRole.DataScope getDataScopeWithNonCustomization(Set<SysRole.DataScope> dataScopes) {
        SysRole.DataScope dataScope = SysRole.DataScope.SELF;
        if (dataScopes.contains(SysRole.DataScope.DEPARTMENT)) {
            dataScope = SysRole.DataScope.DEPARTMENT;
        }
        if (dataScopes.contains(SysRole.DataScope.DEPARTMENT_AND_SUBORDINATE)) {
            dataScope = SysRole.DataScope.DEPARTMENT_AND_SUBORDINATE;
        }
        if (dataScopes.contains(SysRole.DataScope.ALL)) {
            dataScope = SysRole.DataScope.ALL;
        }
        return dataScope;
    }
}
